#include "ms575_algbase.h"
using namespace MeasurE575;

once_flag AlgBase::m_flag;
std::vector< std::shared_ptr<std::condition_variable>> AlgBase::cvarptrVec;
std::vector < std::shared_ptr<std::mutex>  > AlgBase::mtxptrVec;
std::vector <bool> AlgBase::flagVec;
std::vector< std::shared_ptr<std::condition_variable>> AlgBase::cvarptrhighVec;
std::vector < std::shared_ptr<std::mutex>  > AlgBase::mtxptrhighVec;
std::vector <bool> AlgBase::flaghighVec;
std::vector<std::vector<Point2f>> AlgBase::datumBackVec;
std::vector<std::vector<Point2f>> AlgBase::datumHighVec;
std::vector <ParameterClass> AlgBase::m_dataAllVec;

once_flag               AlgBase::m_setStandardValOnceFlag         ;
std::string             AlgBase::m_dir_edge_extraction_parameters ;
std::string             AlgBase::m_dir_template_classifier_model  ;
std::string             AlgBase::m_dir_template_feature_model     ;
std::string             AlgBase::m_dir_template_images            ;
std::map<string, float> AlgBase::m_standardValMap                 ;
string                  AlgBase::m_dir_distance_fitting_model     ;
std::map<std::string, std::vector<float>> AlgBase::m_phypixpara     ;

bool                    AlgBase::m_isSetWorkpieceInfo = false     ;
bool                    AlgBase::m_isLoadXml          = false     ;
string                  AlgBase::m_modeName                       ;
string                  AlgBase::m_xmlFileNamePre                 ;


AlgBase::AlgBase(int n)
{
    std::call_once(m_flag, InitFunAll, n);

    if(!m_isLoadXml) {
        if(!LoadFitPara()) {
            qCritical() << "量测算法：E575加载参数失败";
            return ;
        }
        m_isLoadXml = true;
    }
}

AlgBase::~AlgBase()
{
    if(m_isSetWorkpieceInfo) {
        m_isSetWorkpieceInfo = false;
    }

    if(m_isLoadXml) {
        m_isLoadXml = false;
    }
}

void AlgBase::setNumberOfAlg(const int n)
{
    datumBackVec.resize(n);
    datumHighVec.resize(n);
    AlgBase::cvarptrVec.resize(n);
    AlgBase::mtxptrVec.resize(n);
    AlgBase::flagVec.resize(n);
    AlgBase::cvarptrhighVec.resize(n);
    AlgBase::mtxptrhighVec.resize(n);
    AlgBase::flaghighVec.resize(n);

    for (size_t i = 0; i < AlgBase::flagVec.size(); i++)
    {
        AlgBase::flagVec[i] = false;
        std::shared_ptr<std::condition_variable> cvar(new std::condition_variable());
        std::shared_ptr<std::mutex> mtx(new std::mutex());
        cvarptrVec[i]=cvar;
        mtxptrVec[i] = mtx;

        AlgBase::flaghighVec[i] = false;
        std::shared_ptr<std::condition_variable> cvarhigh(new std::condition_variable());
        std::shared_ptr<std::mutex> mtxhigh(new std::mutex());
        cvarptrhighVec[i] = cvarhigh;
        mtxptrhighVec[i] = mtxhigh;
    }
}

void AlgBase::InitFunAll(const int n)
{
    setNumberOfAlg(n);
    {
        //back circle L12345678-> 01234567
        std::vector<int> toll{0,1,2,3,4,5,6,7};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem+1));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("L")+std::to_string((elem+1))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("L.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }

    {
        //back circle R12345678-> 8,9,10,11,12,13,14,15
        std::vector<int> toll{8,9,10,11,12,13,14,15};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem+1));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("R")+std::to_string((elem-7))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("R.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }

    {
        //back circle D123456789-> 16,17,18,19,20,21,22,23,24
        std::vector<int> toll{16,17,18,19,20,21,22,23,24};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem+1));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("D")+std::to_string((elem-15))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("D.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }

    {
        //back circle S1S2S3S4S5S6-> 25,26,27,28,29,30
        {
            std::vector<int> toll{25,26};
            for_each(toll.begin(),toll.end(),[](int &elem){
                int regionNum=elem;
                std::string  backxml("back.xml");
                cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
                std::string tagname=std::string("temp_info")+std::to_string((elem+1));
                cv::Rect regionRect;
                fs[tagname][std::string("match_region")]>>regionRect;
                fs.release();
                std::string  backImg("back/"),backImgTmp("/best_temp.png");
                std::vector<cv::Mat> imgVec;
                std::string imgname=m_dir_template_images+backImg+std::string("S")+std::to_string((elem-24))+backImgTmp;
                cv::Mat img=cv::imread(imgname.c_str(),0);
                imgVec.push_back(img.clone());
                cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("S.xml")).c_str(),cv::FileStorage::READ);
                ParameterClass obj;
                obj.m_regionNum=regionNum;
                obj.m_templateImageVec=imgVec;
                obj.m_regionRect=regionRect;
                fse["voc"]>>obj.m_edgeParam;
                fse.release();
                m_dataAllVec.push_back(obj);
            });
        }
        {
            std::vector<int> toll{27,28};
            for_each(toll.begin(),toll.end(),[](int &elem){
                int regionNum=elem;
                std::string  backxml("back.xml");
                cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
                std::string tagname=std::string("temp_info")+std::to_string((elem+1));
                cv::Rect regionRect;
                fs[tagname][std::string("match_region")]>>regionRect;
                fs.release();
                std::string  backImg("back/"),backImgTmp("/best_temp.png");
                std::vector<cv::Mat> imgVec;
                std::string imgname=m_dir_template_images+backImg+std::string("S")+std::to_string((elem-24))+backImgTmp;
                cv::Mat img=cv::imread(imgname.c_str(),0);
                imgVec.push_back(img.clone());
                cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("LD.xml")).c_str(),cv::FileStorage::READ);
                ParameterClass obj;
                obj.m_regionNum=regionNum;
                obj.m_templateImageVec=imgVec;
                obj.m_regionRect=regionRect;
                fse["voc"]>>obj.m_edgeParam;
                fse.release();
                m_dataAllVec.push_back(obj);
            });
        }
        {
            std::vector<int> toll{29,30};
            for_each(toll.begin(),toll.end(),[](int &elem){
                int regionNum=elem;
                std::string  backxml("back.xml");
                cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
                std::string tagname=std::string("temp_info")+std::to_string((elem+3));
                cv::Rect regionRect;
                fs[tagname][std::string("match_region")]>>regionRect;
                fs.release();
                std::string  backImg("back/"),backImgTmp("/best_temp.png");
                std::vector<cv::Mat> imgVec;
                std::string imgname=m_dir_template_images+backImg+std::string("S")+std::to_string((elem-24))+backImgTmp;
                cv::Mat img=cv::imread(imgname.c_str(),0);
                imgVec.push_back(img.clone());
                cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("S.xml")).c_str(),cv::FileStorage::READ);
                ParameterClass obj;
                obj.m_regionNum=regionNum;
                obj.m_templateImageVec=imgVec;
                obj.m_regionRect=regionRect;
                fse["voc"]>>obj.m_edgeParam;
                fse.release();
                m_dataAllVec.push_back(obj);
            });

        }
    }
    {
        //back circle SS1SS2-> 31,32
        std::vector<int> toll{31,32};
        for_each(toll.begin(),toll.end(),[](int &elem) {
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-1));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")] >> regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SS")+std::to_string((elem-30))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SS.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }
    {
        //back Setup1Setup2->33,34
        std::vector<int> toll{33,34};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem+3));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SetUp")+std::to_string((elem-32))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("S.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }

    {
        //front SS345678 -> 35,36,37,38,39,40
        std::vector<int> toll{35,36,37,38,39,40};
        for_each(toll.begin(), toll.end(), [](int &elem) {
            int regionNum=elem;
            std::string  backxml("front.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-32));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("front/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SS")+std::to_string((elem-32))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SS.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });

    }
    {
        //front SE345678 -> 41,42,43,44,45,46
        std::vector<int> toll{41,42,43,44,45,46};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("front.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-32));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("front/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string((elem-38))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });

    }

    {
        //high SE1289 -> 47,48,49,50
        std::vector<int> toll{47,48,49,50};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("high.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-46));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("high/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;

            std::string imgname;
            switch (elem)
            {
            case 47:
                imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string(1)+backImgTmp;
                break;
            case 48:
                imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string(2)+backImgTmp;
                break;
            case 49:
                imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string(8)+backImgTmp;
                break;
            case 50:
                imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string(9)+backImgTmp;
                break;
            default:
                break;
            }

            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }
}

bool AlgBase::InitPath(const string &path)
{
    m_dir_edge_extraction_parameters = (path + "/E575/575MeasureData/edge_extraction_parameters/");
    m_dir_template_classifier_model  = (path + "/E575/575MeasureData/template_classifier_model/") ;
    m_dir_template_feature_model     = (path + "/E575/575MeasureData/template_feature_model/");
    m_dir_template_images            = (path + "/E575/575MeasureData/template_images/");
    m_dir_distance_fitting_model     = (path + "/E575/575MeasureData/distance_fitting_model/");

    qDebug() << "init path: " << QString::fromStdString(m_dir_distance_fitting_model);

    auto isDirExist = [](const std::string &dirName) {
        QDir dir(QString::fromStdString(dirName));
        if (!dir.exists()) {
            qCritical() << QString("灰度算法：量测算法E575配置文件路径不存在：%1").arg(QString::fromStdString(dirName));
            return false;
        } else {
            return true;
        }
    };

    if (!isDirExist(m_dir_edge_extraction_parameters)
            || !isDirExist(m_dir_template_classifier_model)
            || !isDirExist(m_dir_template_feature_model)
            || !isDirExist(m_dir_template_images)
            || !isDirExist(m_dir_distance_fitting_model))
    {
        return false;
    }
    qDebug() << "init path success " ;
    return true;
}

bool AlgBase::SetTemplatePath(const string &path)
{
    static bool called      = false;
    static bool initResult  = false;
    if(!called) {
        initResult = InitPath(path);
        called = true;
    }
    return initResult;
}

void AlgBase::SetStandardVal(const std::map<string, float> standardVal)
{
    std::call_once(m_setStandardValOnceFlag, InitStandardVal, standardVal);
}

void AlgBase::SetWorkpieceInfo(const string &modeName, const string &workpieceType)
{
    if(!m_isSetWorkpieceInfo) {
        m_modeName = modeName;
        m_xmlFileNamePre = ("fitpara_" + modeName + "_" + workpieceType + "_");
        std::string xmlfileName = m_xmlFileNamePre;
        m_isSetWorkpieceInfo = true;
    }
}

bool AlgBase::LoadFitPara()
{
    {
        // read fit parameter
        vector<std::string> pyhpixstr = LoadFiles(QString::fromStdString(m_dir_distance_fitting_model), "*.xml");
        std::vector<std::string> faiItemList = {
            "FAI101-S1-Y1-distance",
            "FAI101-S1-Y2-distance",
            "FAI171-SS1-X-distance",
            "FAI172-SS1-Y-distance",
            "FAI183-LD-Y-distance",
            "FAI185-LD-Y-distance",
            "FAI186-LD-X-distance",
            "FAI187-LD-X-distance",
            "FAI188-LD-X-distance",
            "FAI189-LD-X-distance",
            "FAI198-S1-Y-distance",
            "FAI2-SE7-X-distance",
            "FAI200-S2-Y-distance",
            "FAI201-S2-X-distance",
            "FAI209-SS7-Y-distance",
            "FAI210-SS5-Y-distance",
            "FAI211-SS3-Y-distance",
            "FAI232-SE1-SE2-Y-distance",
            "FAI27-S1-X-distance",
            "FAI29-S1-Y-distance",
            "FAI3-SE6-Y-distance",
            "FAI30-D-diam",
            "FAI34-L-diam",
            "FAI35-L-X-distance",
            "FAI35-L-Y-distance",
            "FAI35-L-position",
            "FAI38-R-diam",
            "FAI39-R-X-distance",
            "FAI39-R-Y-distance",
            "FAI39-R-position",
            "FAI4-SE3-SE6-Y-distance",
            "FAI44-S1-X-parallelism",
            "FAI45-S1-Y-parallelism",
            "FAI46-D-X-distance",
            "FAI46-D-Y-distance",
            "FAI46-D-position",
            "FAI47-D-roundness",
            "FAI48-L-roundness",
            "FAI49-R-roundness",
            "FAI5-SE5-Y-distance",
            "FAI6-SE1-SE9-Y-distance",
            "FAI7-SE4-X-distance",
            "FAI76-SS5-X-distance",
            "FAI81-SS7-X-distance",
            "FAI81-SS7-Y-distance",
            "FAI82-SS2-Y-distance",
            "FAI83-SS6-Y-distance",
            "FAI84-SS8-Y-distance",
            "FAI85-SS4-Y-distance",
            "FAI88-SS2-X-distance",
            "FAI89-SS6-X-distance",
            "FAI90-SS4-X-distance",
            "FAI91-SS8-X-distance",
            "FAI92-SS3-X-distance",
            "FAI209-SS7-X-distance",
            "FAI227-S1-X-distance",
            "Line-B-parallelism",
            "Line-C-parallelism",
            "Line-D-parallelism",
            "Line-E-parallelism",
            "Line-F-parallelism",
            "Line-G-parallelism",
            "S1-diam",
            "S2-diam",
            "S3-diam",
            "S4-diam",
            "S5-diam",
            "S6-diam",
            "S7-diam",
            "S8-diam",
            "FAI3-SE6-Y1-distance",
            "FAI3-SE6-Y2-distance",
            "FAI3-SE6-Y3-distance",
            "FAI4-SE3-SE6-Y1-distance",
            "FAI4-SE3-SE6-Y2-distance",
            "FAI4-SE3-SE6-Y3-distance",
            "FAI6-SE1-SE9-Y1-distance",
            "FAI6-SE1-SE9-Y2-distance",
            "FAI6-SE1-SE9-Y3-distance",
            "FAI7-SE4-X1-distance",
            "FAI7-SE4-X2-distance",
            "FAI7-SE4-X3-distance",
            "FAI7-SE4-X4-distance",
            "FAI7-SE4-X5-distance",
            "FAI27-S1-X1-distance",
            "FAI27-S1-X2-distance",
            "FAI27-S1-X3-distance",
            "FAI29-S1-Y1-distance",
            "FAI29-S1-Y2-distance",
            "FAI29-S1-Y3-distance"
        };

        auto LoadFitPara_ = [&](const FileStorage& fs,
                const std::string &prefix,
                const std::string &name,
                std::map<std::string, std::vector<float>>& phypixpara)
        {
            for(size_t i = 0; i < 3; i++)
            {
                phypixpara[prefix + std::string(name)].push_back(static_cast<float>(fs[std::string(name)][i]));
            }
        };

        for(size_t i = 0; i < pyhpixstr.size(); i++) {
            try {
                FileStorage fs((m_dir_distance_fitting_model + pyhpixstr[i]).c_str(),FileStorage::READ);

                std::string faiPre;
                size_t found = pyhpixstr[i].find(".xml");

                faiPre = (pyhpixstr[i].substr(0, found) + "_");

                for(auto &item : faiItemList) {
                    LoadFitPara_(fs, faiPre, item, m_phypixpara);
                }
                fs.release();
            } catch(cv::Exception &ex) {
                qCritical() << "cv algrithm: E575 load xml fail : "
                            << "****************************\n"
                            << QString::fromStdString(ex.err);
                return false;
            }
        }
        return true;
    }
}

vector<string> AlgBase::LoadFiles(const QString &path, QString ext)
{
    QDir dir(path);
    QStringList nameFilters;
    nameFilters << ext;
    QStringList files = dir.entryList(nameFilters, QDir::Files | QDir::Readable, QDir::Name);

    vector<std::string> fileList;
    for(auto &file : files) {
        fileList.push_back(file.toStdString());
    }

    return fileList;
}

void AlgBase::InitStandardVal(const std::map<string, float> standardVal)
{
    for (auto &iter : standardVal) {
        m_standardValMap[iter.first] = iter.second;
    }
}

void AlgBase::TemplateMatch(cv::Mat &img, ParameterClass &obj,std::vector<cv::Rect> &rangVec)
{
    cv::Mat templ=obj.m_templateImageVec[0];
    int result_cols =  img.cols - templ.cols + 1;
    int result_rows = img.rows - templ.rows + 1;
    cv::Mat result;
    result.create( result_cols, result_rows, CV_32FC1 );
    cv::Mat imgRoi=img(obj.m_regionRect);
    matchTemplate( imgRoi, templ, result,  CV_TM_CCOEFF_NORMED );
    normalize( result, result, 0, 1, NORM_MINMAX, -1, cv::Mat() );
    double minVal;
    double maxVal;
    cv::Point minLoc; cv::Point maxLoc;
    cv::Point matchLoc;
    minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
    matchLoc.x=maxLoc.x+obj.m_regionRect.x;
    matchLoc.y=maxLoc.y+obj.m_regionRect.y;

    cv::Rect rz;
    rz.x = matchLoc.x;
    rz.y = matchLoc.y;
    rz.width = templ.cols;
    rz.height= templ.rows;
    rangVec.push_back(rz);
}

void AlgBase::CoordinateTransformationRelateToDot(const std::vector<Point2f> &ptsVec,
                                                  const Point2f &ptsIn,
                                                  Point2f &ptsOut)
{
    ptsOut.x = ptsIn.x - ptsVec[0].x;
    ptsOut.y = ptsIn.y - ptsVec[0].y;
}

void AlgBase::CoordinateTransformation(std::vector<cv::Point2f> &ptsVec, cv::Point2f &ptsIn,cv::Point2f &ptsOut)
{
    float A1=0.0,B1=0.0,C1=0.0;
    float A2=0.0,B2=0.0,C2=0.0;
    A1=ptsVec[1].y-ptsVec[0].y;
    B1=ptsVec[0].x-ptsVec[1].x;
    C1=ptsVec[0].y*ptsVec[1].x-ptsVec[0].x*ptsVec[1].y;
    ptsOut.y=abs(A1*ptsIn.x+B1*ptsIn.y+C1)/sqrt(A1*A1+B1*B1);

    A2=ptsVec[2].y-ptsVec[0].y;
    B2=ptsVec[0].x-ptsVec[2].x;
    C2=ptsVec[0].y*ptsVec[2].x-ptsVec[0].x*ptsVec[2].y;
    ptsOut.x=abs(A2*ptsIn.x+B2*ptsIn.y+C2)/sqrt(A2*A2+B2*B2);

}

void AlgBase::clearAllflag(int id)
{
    if(-1 != id) {
        AlgBase::flagVec[id] = false;
        AlgBase::flaghighVec[id] = false;
    }
}

float AlgBase::CalcMeasureDistance(const vector<float> &coefficient, float measureItem)
{
    if(coefficient.empty()) {
        qCritical() << "empty coefficient";
        Q_ASSERT(coefficient.size() != 0);
        return -1;
    }

    return coefficient[0]*measureItem*measureItem + coefficient[1]*measureItem + coefficient[2];
}

float AlgBase::CalcPixelAccordExpectDist(const vector<float> &coefficient, float expectDist)
{
    if(coefficient.empty()) {
        qCritical() << "empty coefficient";
        Q_ASSERT(coefficient.size() != 0);
        return -1;
    }

    float ret = 0.0f;
    if(0 != coefficient[1]) {
        ret = (expectDist - coefficient[2])/coefficient[1];
    }
    return ret;
}

float AlgBase::CalcPosition(const std::string &measureItemX,
                            const std::string &measureItemY,
                            const std::string &measureItemPos,
                            const std::string &prefix,
                            edgedetect &obj,
                            float expectRealDistX,
                            float expectRealDistY,
                            float predictPixelX,
                            float predictPixelY,
                            std::map<string, float> &measRes)
{
    if(measureItemX.empty() ||
       measureItemY.empty() ||
       measureItemPos.empty())
    {
        Q_ASSERT(measureItemX.empty());
        qCritical() << "cv_measure_575 input empty measure item";
        return -1;
    }

    float faiPosPixelX = CalcPixelAccordExpectDist(m_phypixpara[prefix + measureItemX],
            expectRealDistX);
    float faiPosPixelY = CalcPixelAccordExpectDist(m_phypixpara[prefix + measureItemY],
            expectRealDistY);
    double faiPosPixel = obj.GetPosition(cv::Point2f(predictPixelX, predictPixelY),
                                         cv::Point2f(faiPosPixelX, faiPosPixelY)
                                        );
    std::string measureItemPosPixel = measureItemPos + "_pixel";
    std::string measureItemPosReal  = measureItemPos + "_real";
    measRes.insert(std::make_pair(string(measureItemPosPixel), faiPosPixel));
    float faiPosDis = CalcMeasureDistance(m_phypixpara[prefix + std::string(measureItemPos)], faiPosPixel);
    measRes.insert(std::make_pair(string(measureItemPosReal), faiPosDis));
}

//void AlgBase::TemplateMatch(cv::Mat &img, int &&num, std::vector<Rect> &rangVec)
//{

// rangVec.resize(num.m_templateImageVec.size());
//#pragma omp parallel for num_threads(6)
//    for(int i=0;i<int(num.m_templateImageVec.size());i++)
//    {
//        cv::Mat templ=num.m_templateImageVec[i];
//        int result_cols =  img.cols - templ.cols + 1;
//        int result_rows = img.rows - templ.rows + 1;
//        cv::Mat result;
//        result.create( result_cols, result_rows, CV_32FC1 );
//        cv::Mat imgRoi=img(num.m_regionRect);
//        matchTemplate( imgRoi, templ, result,  CV_TM_CCOEFF_NORMED );
//        normalize( result, result, 0, 1, NORM_MINMAX, -1, cv::Mat() );
//        double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
//        cv::Point matchLoc;
//        minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
//        matchLoc=maxLoc;
//        cv::Rect rz;
//        rz.x=matchLoc.x,rz.y=matchLoc.y,rz.width=templ.cols,rz.height=templ.rows;
//        rangVec.push_back(rz);
//    }

//}

